"""
Channels inherit from the expectable class, which adds expect functionality to
anything implementing the channel interface.

Copyright (c) 2009 Christopher Hesse
http://code.google.com/p/python-expect/
"""

from .base import expect


class Expectable(object):
    """
    This class adds expect functionality to a class, channels should inherit
    from this class.
    """
    def __init__(self, buffer_size=None, **kwargs):
        super(Expectable, self).__init__(**kwargs)
        # maximum bytes to save when reading from a channel
        self.buffer_size = buffer_size
        # buffer for data read from the channel
        self.read_buffer = ""
        
    def clear(self):
        """
        Clear this channel's read buffer.
        """
        self.read_buffer = ""
        
    def expect(self, patterns_or_handler, timeout=60):
        """
        This method looks at the output of this channel and compares
        the provided patterns to it until it finds a match, times out,
        or the channel closes.
        
        This method accepts 3 different pattern types, PatternHandler
        instances, strings, and regular expressions.
        
        For strings and regular expressions, you can pass a list:
        
            ["string1", "string2", ...]
        
        a dictionary:
        
            {'name1': "string1", 'name2': "string2", ...}
            
        or an ordered dictionary/list of tuples:
        
            [('name1', "string1"), ('name2', "string2"), ...]
            
        All expect calls return an ExpectResult instance. The instance
        has .index and .name attributes.  In the case of a normal list, these
        are both 0, 1, etc, the index of the pattern that matched.
        
        In the case of a dictionary, the name is the key for the pattern
        and the index is its position in the dictionary.
        
        Using the expect method looks like this:
        
            result = channel.expect(["login:", "password:"], 60)
            if result == "login:":
                channel.send(username)
            elif result == "password:":
                channel.send(password)
        
        If the expect operation times out, it raises an error unless you
        pass Timeout as one of the patterns, in which case, result will
        be equal to Timeout if there is a timeout.
        
        The same goes for a channel being closed when expecting on it.
        A ChannelClosed exception is raised in that case, add it to the
        patterns list to avoid that.
        
            result = channel.expect(["login:", "password:", Timeout, ChannelClosed], 60)
            if result == "login:":
                channel.send(username)
            elif result == "password:":
                channel.send(password)
            elif result == Timeout:
                print "timeout"
            elif result == ChannelClosed:
                print "channel closed"
        
        For PatternHandlers, you just pass in a PatternHandler instance.
        See the PatternHandler documentation for more information.
        
        'timeout' is the maximum time to wait in seconds for a pattern to
        match. If timeout is None, wait forever.
        """
        return expect(self, patterns_or_handler, timeout)